home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / net / rhslip38_9_030.lha / rhslip / src / cslip.c < prev    next >
C/C++ Source or Header  |  1994-01-26  |  19KB  |  665 lines

  1. /* $Id: cslip.c,v 1.1 1993/08/17 00:00:00 rhialto Exp $
  2.  *
  3.  *            COMPRESSED TCP HEADERS
  4.  *
  5.  * Reduce the 40 byte TCP header to as little as 5 or even 3 bytes
  6.  * (of which 2 bytes are the original TCP checksum).
  7.  *
  8.  * See RFC 1144 "Compression of TCP/IP Headers for Low-Speed Serial
  9.  * Links", V. Jacobson, February 1990, for the exciting details.
  10.  *
  11.  * The code in this file is derived from and very similar to the example
  12.  * implementation provided in RFC 1144, and is therefore sort-of covered
  13.  * by its copyright:
  14.  *
  15.  * Copyright (C) 1989 Regents of the University of California.
  16.  *
  17.  * This adaptation by Olaf 'Rhialto' Seibert.
  18.  * - fixed a number of sizeof(int) == 4 assumptions.
  19.  * - allow a few packets to be sent compressed before it is officially
  20.  *   enabled, so as to trigger the other side into compressed mode.
  21.  *
  22.  * Memory usage: < 3K of 68000 code, plus ~ 4K buffer space per line.
  23.  */
  24.  
  25. #include <string.h>
  26. #include "slip_device.h"
  27. #if DEBUG
  28. #include "syslog.h"
  29. #else
  30. #define debug(x)
  31. #endif
  32.  
  33. #define calloc(n,m)     AllocVec((n) * (m), MEMF_CLEAR)
  34. #define free(p)         FreeVec(p)
  35.  
  36. #ifndef EXEC_MEMORY_H
  37. #include <exec/memory.h>
  38. #endif
  39. #include <clib/exec_protos.h>
  40. #ifdef __SASC
  41. #include <pragmas/exec_pragmas.h>
  42. #endif
  43.  
  44. #define ihl(v_ihl)      lonibble(v_ihl) /* extract ip header length */
  45. #define tcp_offset(tcp)  ((u_char)(tcp)->offset >> DSHIFT)
  46.  
  47. /* Appendix A.2  Compression */
  48.  
  49. u_char
  50. sl_compress_tcp(m, comp)
  51. struct mbuf *m;
  52. struct slcompress *comp;
  53. {
  54.     register struct cstate *cs = comp->last_cs->cs_next;
  55.     register struct ip_header *ip = mtod(m, struct ip_header *);
  56.     register u_int hlen = ihl(ip->v_ihl);
  57.     register struct tcp_header *oth;    /* last TCP header */
  58.     register struct tcp_header *th;    /* current TCP header */
  59.     register u_long deltaS, deltaA;    /* general purpose temporaries */
  60.     register u_int changes = 0;     /* change mask */
  61.     u_char new_seq[16];         /* changes from last to current */
  62.     register u_char *cp = new_seq;
  63.  
  64.     debug((">sl_compress_tcp %lx %d\n", m->m_off, m->m_len));
  65.     /* Appendix B.2  Backwards compatible SLIP servers */
  66. #ifdef TRYCOUNT
  67.     if (comp->on == 0) {
  68.     debug(("<sl_compress_tcp: not on\n"));
  69.     return TYPE_IP;
  70.     }
  71. #else
  72.     if ((comp->flags & SLF_ON) == 0) {
  73.     debug(("<sl_compress_tcp: not on\n"));
  74.     return TYPE_IP;
  75.     }
  76. #endif
  77.  
  78.     if (ip->protocol != TCP_PTCL) {     /* Rhialto */
  79.     comp->sls_o_nontcp++;
  80.     debug(("<sl_compress_tcp: not tcp\n"));
  81.     return TYPE_IP;
  82.     }
  83.  
  84.     /*
  85.      * Bail if this is an IP fragment or if the TCP packet isn't
  86.      * `compressible' (i.e., ACK isn't set or some other control bit is
  87.      * set). (We assume that the caller has already made sure the packet
  88.      * is IP proto TCP).
  89.      */
  90.     if ((ip->fl_offs & htons(0x3fff)) || m->m_len < 40) {
  91.     comp->sls_o_tcp++;
  92.     debug(("<sl_compress_tcp: tcp frag\n"));
  93.     return TYPE_IP;
  94.     }
  95.  
  96.     th = (struct tcp_header *)&((int32 *) ip)[hlen];
  97.     if ((th->flags & (SYN | FIN | RST | ACK)) != ACK) {
  98.     comp->sls_o_tcp++;
  99.     debug(("<sl_compress_tcp: tcp flags\n"));
  100.     return TYPE_IP;
  101.     }
  102.  
  103.     /*
  104.      * Packet is compressible -- we're going to send either a
  105.      * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need to
  106.      * locate (or create) the connection state. Special case the most
  107.      * recently used connection since it's most likely to be used again &
  108.      * we don't have to do any reordering if it's used.
  109.      */
  110.     if (ip->source != cs->cs_ip.source ||
  111.     ip->dest != cs->cs_ip.dest ||
  112.     *(int32 *)th != cs->cs_hdr4[ihl(cs->cs_ip.v_ihl)]) {
  113.  
  114.     /*
  115.      * Wasn't the first -- search for it.
  116.      *
  117.      * States are kept in a circularly linked list with last_cs
  118.      * pointing to the end of the list. The list is kept in lru
  119.      * order by moving a state to the head of the list whenever
  120.      * it is referenced. Since the list is short and,
  121.      * empirically, the connection we want is almost always near
  122.      * the front, we locate states via linear search. If we don't
  123.      * find a state for the datagram, the oldest state is re-used.
  124.      */
  125.     register struct cstate *lcs;
  126.     register struct cstate *lastcs = comp->last_cs;
  127.  
  128.     do {
  129.         lcs = cs;
  130.         cs = cs->cs_next;
  131.         comp->sls_o_searches++;
  132.  
  133.         if (ip->source == cs->cs_ip.source &&
  134.         ip->dest == cs->cs_ip.dest &&
  135.         *(int32 *)th == cs->cs_hdr4[ihl(cs->cs_ip.v_ihl)])
  136.         goto found;
  137.     } while (cs != lastcs);
  138.  
  139.     /*
  140.      * Didn't find it -- re-use oldest cstate. Send an uncompressed
  141.      * packet that tells the other side what connection number
  142.      * we're using for this conversation. Note that since the
  143.      * state list is circular, the oldest state points to the newest
  144.      * and we only need to set last_cs to update the lru linkage.
  145.      */
  146.     comp->sls_o_misses++;
  147.     comp->last_cs = lcs;
  148.     hlen += tcp_offset(th); /* add tcp header length */
  149.     hlen *= sizeof(int32);
  150.  
  151.     goto uncompressed;
  152.  
  153.     found:
  154.     /* Found it -- move to the front on the connection list. */
  155.     if (lastcs == cs)
  156.         comp->last_cs = lcs;
  157.     else {
  158.         lcs->cs_next = cs->cs_next;
  159.         cs->cs_next = lastcs->cs_next;
  160.         lastcs->cs_next = cs;
  161.     }
  162.     }
  163.     debug((" sl_compress_tcp: found\n"));
  164. #ifdef TRYCOUNT
  165.     /*
  166.      * For found connections, try a few TCP_UNCOMPRESSED packets even if
  167.      * we're not SL_ON yet. (This doesn't happen on new connections;
  168.      * they will be TCP_UNCOMPRESSED regardless - FIXME.)
  169.      */
  170.     if (comp->on > 0) {
  171.     comp->on--;
  172.     debug((" sl_compress_tcp: trycount %d\n", comp->on));
  173.     goto uncompressed;
  174.     }
  175. #endif
  176.     /*
  177.      * Make sure that only what we expect to change changed. The 1st
  178.      * line of the 'if' checks the IP protocol version, header length &
  179.      * type of service. The 2nd line checks the "Don't fragment" bit.
  180.      * The 3rd line checks the time-to-live and protocol (the protocol
  181.      * check is unnecessary but costless). The 4th line checks the TCP
  182.      * header length. The 5th line checks IP options, if any. The 6th
  183.      * line checks TCP options, if any. If any of these things are
  184.      * different between the previous & current datagram, we send the
  185.      * current datagram "uncompressed".
  186.      */
  187.     oth = (struct tcp_header *) &cs->cs_hdr4[hlen];
  188.     deltaS = hlen;
  189.     hlen += tcp_offset(th);
  190.     hlen *= sizeof(int32);
  191.  
  192.     if (((u_short *) ip)[0] != ((u_short *) &cs->cs_ip)[0] || /* v_ihl,tos */
  193.     ((u_short *) ip)[3] != ((u_short *) &cs->cs_ip)[3] || /* fl_offs */
  194.     ((u_short *) ip)[4] != ((u_short *) &cs->cs_ip)[4] || /* ttl, protocol */
  195.     th->offset != oth->offset ||
  196.     (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) * sizeof(int32))) ||
  197.     (tcp_offset(th) > 5 && BCMP(th + 1, oth + 1, (tcp_offset(th) - 5) * sizeof(int32)))) {
  198.     debug((" sl_compress_tcp: header changed\n"));
  199.     goto uncompressed;
  200.     }
  201.  
  202.     /*
  203.      * Figure out which of the changing fields changed. The receiver
  204.      * expects changes in the order: urgent, window, ack, seq.
  205.      */
  206.     if (th->flags & URG) {
  207.     deltaS = ntohs(th->up);
  208.     ENCODEZ(deltaS);
  209.     changes |= NEW_U;
  210.     } else if (th->up != oth->up) {
  211.     /*
  212.      * argh! URG not set but urp changed -- a sensible
  213.      * implementation should never do this but RFC 793 doesn't
  214.      * prohibit the change so we have to deal with it.
  215.      */
  216.     debug((" sl_compress_tcp: up changed\n"));
  217.     goto uncompressed;
  218.     }
  219.  
  220.     if (deltaS = (u_short) (ntohs(th->wnd) - ntohs(oth->wnd))) {
  221.     ENCODE(deltaS);
  222.     changes |= NEW_W;
  223.     }
  224.     if (deltaA = ntohs(th->ack) - ntohs(oth->ack)) {
  225.     if (deltaA > 0xffff)
  226.         goto uncompressed;
  227.     ENCODE(deltaA);
  228.     changes |= NEW_A;
  229.     }
  230.     if (deltaS = ntohs(th->seq) - ntohs(oth->seq)) {
  231.     if (deltaS > 0xffff)
  232.         goto uncompressed;
  233.     ENCODE(deltaS);
  234.     changes |= NEW_S;
  235.     }
  236.     /*
  237.      * Look for the special-case encodings.
  238.      */
  239.     switch (changes) {
  240.  
  241.     case 0:
  242.     /*
  243.      * Nothing changed. If this packet contains data and the last
  244.      * one didn't, this is probably a data packet following an
  245.      * ack (normal on an interactive connection) and we send it
  246.      * compressed. Otherwise it's probably a retransmit,
  247.      * retransmitted ack or window probe. Send it uncompressed
  248.      * in case the other side missed the compressed version.
  249.      */
  250.     if (ip->length != cs->cs_ip.length &&
  251.         ntohs(cs->cs_ip.length) == hlen)
  252.         break;
  253.  
  254.     debug((" sl_compress_tcp: retransmission ->\n"));
  255.     /* fall through */
  256.  
  257.     case SPECIAL_I:
  258.     case SPECIAL_D:
  259.     /*
  260.      * Actual changes match one of our special case encodings --
  261.      * send the packet uncompressed.
  262.      */
  263.     debug((" sl_compress_tcp: changes match special\n"));
  264.     goto uncompressed;
  265.  
  266.     case NEW_S | NEW_A:
  267.     if (deltaS == deltaA &&
  268.         deltaS == ntohs(cs->cs_ip.length) - hlen) {
  269.         /* special case for echoed terminal traffic */
  270.         debug((" sl_compress_tcp: special interactive\n"));
  271.         changes = SPECIAL_I;
  272.         cp = new_seq;
  273.     }
  274.     break;
  275.  
  276.     case NEW_S:
  277.     if (deltaS == ntohs(cs->cs_ip.length) - hlen) {
  278.         /* special case for data xfer */
  279.         debug((" sl_compress_tcp: special data\n"));
  280.         changes = SPECIAL_D;
  281.         cp = new_seq;
  282.     }
  283.     break;
  284.     }
  285.     deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
  286.     if (deltaS != 1) {
  287.     ENCODEZ(deltaS);
  288.     changes |= NEW_I;
  289.     }
  290.     if (th->flags & PSH)
  291.     changes |= TCP_PUSH_BIT;
  292.     /*
  293.      * Grab the cksum before we overwrite it below. Then update our
  294.      * state with this packet's header.
  295.      */
  296.     deltaA = ntohs(th->checksum);
  297.     BCOPY(ip, &cs->cs_ip, hlen);
  298.  
  299.     /*
  300.      * We want to use the original packet as our compressed packet.
  301.      * (cp - new_seq) is the number of bytes we need for compressed
  302.      * sequence numbers. In addition we need 1 byte for the change
  303.      * mask, 1 for the connection id and 2 for the tcp checksum.
  304.      * So, (cp - new_seq) + 4 bytes of header are needed.
  305.      * hlen is how many bytes of the original packet we tossed so
  306.      * subtract the two to to get the packet size difference.
  307.      */
  308.  
  309.     deltaS = cp - new_seq;
  310.     cp = (u_char *)ip;
  311.     if (comp->last_xmit != cs->cs_id) {
  312.     comp->last_xmit = cs->cs_id;
  313.     hlen -= deltaS + 4;
  314.     cp += hlen;
  315.     *cp++ = changes | NEW_C;
  316.     *cp++ = cs->cs_id;
  317.     } else {
  318.     hlen -= deltaS + 3;
  319.     cp += hlen;
  320.     *cp++ = changes;
  321.     }
  322.     m->m_len -= hlen;
  323.     m->m_off += hlen;
  324.     *cp++ = deltaA >> 8;    /* checksum */
  325.     *cp++ = deltaA;
  326.     BCOPY(new_seq, cp, deltaS);
  327.  
  328.     comp->sls_o_compressed++;
  329.     debug(("<sl_compress_tcp: compressed\n"));
  330.     return TYPE_COMPRESSED_TCP;
  331.  
  332. uncompressed:
  333.     debug((" sl_compress_tcp: uncompressed\n"));
  334.     /*
  335.      * Update connection state cs & send uncompressed packet
  336.      * ('uncompressed' means a regular ip/tcp packet but with the
  337.      * 'conversation id' we hope to use on future compressed packets
  338.      * in the protocol field).
  339.      */
  340.     BCOPY(m->m_off, cs->cs_hdr, hlen);
  341.     ip->protocol = cs->cs_id;
  342.     comp->last_xmit = cs->cs_id;
  343.  
  344.     comp->sls_o_uncompressed++;
  345.     debug(("<sl_compress_tcp: uncompressed\n"));
  346.     return TYPE_UNCOMPRESSED_TCP;
  347. }
  348.  
  349. /* OIS:
  350.  * This function should be called if the most recently compressed packet
  351.  * may have been lost on its way to the next gateway. It forces the next
  352.  * packet on the same connection to be uncompressed, in an attempt to
  353.  * minimise the effect of the dropped packet. The method used is to change
  354.  * one of the 'unchanging' header fields in the saved header, so that none
  355.  * of the other saved headers will be dropped.
  356.  */
  357. void
  358. sl_xmit_error(comp)
  359. struct slcompress *comp;
  360. {
  361.     if (comp->last_xmit < MAX_STATES) {
  362.     comp->tstate[comp->last_xmit].cs_ip.v_ihl--;
  363.     }
  364. }
  365.  
  366. /* Appendix A.3  Decompression */
  367.  
  368. struct mbuf *
  369. sl_uncompress_tcp(m, type, comp)
  370. struct mbuf *m;
  371. u_int type;
  372. struct slcompress *comp;
  373. {
  374.     register char *bufp;
  375.     register u_char *cp;
  376.     register u_int hlen, changes;
  377.     register struct tcp_header *th;
  378.     register struct cstate *cs;
  379.     register struct ip_header *ip;
  380.     int len;
  381.  
  382.     debug((">sl_uncompress_tcp\n"));
  383.  
  384.     switch (type) {
  385.     case TYPE_ERROR:
  386.     default:
  387.     debug((" sl_uncompress_tcp: ERROR\n"));
  388.     goto bad;
  389.     case TYPE_IP:
  390.     debug((" sl_uncompress_tcp: IP\n"));
  391.     comp->sls_i_ip++;
  392. #ifdef SLF_MAYBE
  393.     /*
  394.      * If we receive TYPE_IP packets, investigate if they could have
  395.      * been sent compressed. If so, the other side probably doesn't
  396.      * understand compressed packets. This test is identical to those
  397.      * in sl_compress_tcp().
  398.      * (OIS)
  399.      */
  400.     bufp = m->m_off;
  401.     ip = (struct ip_header *)bufp;
  402.     if (comp->flags & SLF_MAYBE &&
  403.         ip->protocol == TCP_PTCL &&
  404.         (ip->fl_offs & htons(0x3fff)) == 0 &&
  405.         (th = (struct tcp_header *)
  406.          offset(m, ihl(ip->v_ihl) * sizeof(int32), sizeof(*th))) &&
  407.         (th->flags & (SYN | FIN | RST | ACK)) == ACK) {
  408.         comp->flags &= ~(SLF_ON | SLF_MAYBE) ;
  409.         /* printf("Compression turned OFF\n"); */
  410.     }
  411. #endif
  412.     return m;
  413.     case TYPE_UNCOMPRESSED_TCP:
  414.     debug((" sl_uncompress_tcp: UNCOMPRESSED TCP\n"));
  415.     comp->sls_i_uncompressed++;
  416.     /* Appendix B.2  Backwards compatible SLIP servers */
  417.     if ((comp->flags & SLF_ALLOWED) == 0)
  418.         goto bad;
  419. #ifdef TRYCOUNT
  420.     comp->on = SL_ON;
  421. #else
  422.     comp->flags |= SLF_ON;
  423. #endif
  424.     /*
  425.      * Locate the saved state for this connection. If the state index
  426.      * is legal, clear the 'discard' flag.
  427.      */
  428.     bufp = m->m_off;
  429.     ip = (struct ip_header *)bufp;
  430.     if (ip->protocol > comp->rslot_limit)
  431.         goto bad;
  432.  
  433.     cs = &comp->rstate[comp->last_recv = ip->protocol];
  434.     comp->flags &= ~SLF_TOSS;
  435.     /*
  436.      * Restore the IP protocol field then save a copy of this
  437.      * packet header. (The checksum is zeroed in the copy so we
  438.      * don't have to zero it each time we process a compressed
  439.      * packet.)
  440.      */
  441.     ip->protocol = TCP_PTCL;
  442.     hlen = ihl(ip->v_ihl);
  443.     hlen += tcp_offset((struct tcp_header *) & ((int32 *)ip)[hlen]);
  444.     hlen *= sizeof(int32);
  445.     BCOPY(ip, cs->cs_hdr, hlen);
  446.     cs->cs_ip.checksum = 0;
  447.     cs->cs_hlen = hlen;
  448.  
  449.     return m;
  450.  
  451.     case TYPE_COMPRESSED_TCP:
  452.     debug((" sl_uncompress_tcp: COMPRESSED TCP\n"));
  453.     comp->sls_i_compressed++;
  454.     /* Appendix B.2  Backwards compatible SLIP servers */
  455.     if ((comp->flags & SLF_ALLOWED) == 0)
  456.         goto bad;
  457.     break;
  458.     }
  459.  
  460.     /* We've got a compressed packet. */
  461.     bufp = m->m_off;
  462.     cp = bufp;
  463.     changes = *cp++;
  464.     if (changes & NEW_C) {
  465.     /*
  466.      * Make sure the state index is in range, then grab the
  467.      * state. If we have a good state index, clear the 'discard'
  468.      * flag.
  469.      */
  470.     if (*cp > comp->rslot_limit)
  471.         goto bad;
  472.  
  473.     comp->flags &= ~SLF_TOSS;
  474.     comp->last_recv = *cp++;
  475.     } else {
  476.     /*
  477.      * This packet has an implicit state index. If we've had a
  478.      * line error since the last time we got an explicit state
  479.      * index, we have to toss the packet.
  480.      */
  481.     if (comp->flags & SLF_TOSS) {
  482.         comp->sls_i_tossed++;
  483.         debug(("<sl_uncompress_tcp: tossed\n"));
  484.         return NULL;
  485.     }
  486.     }
  487.  
  488.     /*
  489.      * Find the state then fill in the TCP checksum and PUSH bit.
  490.      */
  491.     cs = &comp->rstate[comp->last_recv];
  492.     hlen = ihl(cs->cs_ip.v_ihl) * sizeof(int32);
  493.     th = (struct tcp_header *) &((u_char *) &cs->cs_ip)[hlen];
  494.     th->checksum = htons((*cp << 8) | cp[1]);
  495.     cp += 2;
  496.     if (changes & TCP_PUSH_BIT)
  497.     th->flags |= PSH;
  498.     else
  499.     th->flags &= ~PSH;
  500.  
  501.     /*
  502.      * Fix up the state's ack, seq, urg and win fields based on the
  503.      * changemask.
  504.      */
  505.     switch (changes & SPECIALS_MASK) {
  506.     case SPECIAL_I:
  507.     {
  508.         register u_int i = ntohs(cs->cs_ip.length) - cs->cs_hlen;
  509.         debug((" sl_uncompress_tcp: special interactive\n"));
  510.  
  511.         th->ack = htonl(ntohl(th->ack) + i);
  512.         th->seq = htonl(ntohl(th->seq) + i);
  513.     }
  514.     break;
  515.     case SPECIAL_D:
  516.         debug((" sl_uncompress_tcp: special data\n"));
  517.     th->seq = htonl(ntohl(th->seq) + ntohs(cs->cs_ip.length)
  518.             - cs->cs_hlen);
  519.     break;
  520.     default:
  521.     debug((" sl_uncompress_tcp: other changemask\n"));
  522.     if (changes & NEW_U) {
  523.         th->flags |= URG;
  524.         DECODEU(th->up);
  525.     } else
  526.         th->flags &= ~URG;
  527.     if (changes & NEW_W)
  528.         DECODES(th->wnd);
  529.     if (changes & NEW_A)
  530.         DECODEL(th->ack);
  531.     if (changes & NEW_S)
  532.         DECODEL(th->seq);
  533.     }
  534.  
  535.     /* Update the new IP ID */
  536.     if (changes & NEW_I)
  537.     DECODES(cs->cs_ip.id)
  538.     else
  539.     cs->cs_ip.id = htons(ntohs(cs->cs_ip.id) + 1);
  540.  
  541.     /*
  542.      * At this point we have done the whole header.
  543.      * cp points to the first byte of data in the packet. We skip the
  544.      * 4-byte alignment here as SANA will copy it to the user anyway.
  545.      * Back up cp by the TCP/IP header length to make room for the
  546.      * reconstructed header (we assume the packet we were handed has
  547.      * enough space to prepend 128 bytes of header). Adjust the length
  548.      * to account for the new header & fill in the IP total length.
  549.      *
  550.      */
  551.     len = m->m_len;
  552.     len -= (cp - bufp);
  553.     if (len < 0)
  554.     /*
  555.      * We must have dropped some characters (crc should detect this
  556.      * but the slip framing won't)
  557.      */
  558.     goto bad;
  559.  
  560. #if 0
  561.     if ((int32)cp & 3) {
  562.     if (len > 0)
  563.         OVBCOPY(cp, (int32)cp & ~3, len);
  564.     cp = (u_char *) ((int32)cp & ~3);
  565.     }
  566. #endif
  567.  
  568.     m->m_off = cp -= cs->cs_hlen;
  569.     m->m_len = len += cs->cs_hlen;
  570.     cs->cs_ip.length = htons(len);
  571.     debug((" sl_uncompress_tcp: copy long header into packet\n"));
  572.     BCOPY(&cs->cs_ip, cp, cs->cs_hlen);
  573.  
  574.     /* recompute the ip header checksum */
  575.     {
  576.     /*register u_short *bp = (u_short *)cp;*/
  577.     register u_short *bp = (u_short *)&cs->cs_ip;
  578.  
  579.     for (changes = 0; hlen > 0; hlen -= 2)
  580.         changes += ntohs(*bp++);
  581.     changes = (changes & 0xffff) + (changes >> 16);
  582.     changes = (changes & 0xffff) + (changes >> 16);
  583.     changes = htons(~changes);
  584.     bp = &((struct ip_header *)cp)->checksum;
  585.     ((u_char *)bp)[0] = changes >> 8;
  586.     ((u_char *)bp)[1] = changes;
  587.     }
  588.  
  589.     debug(("<sl_uncompress_tcp: done\n"));
  590.     return m;
  591.  
  592. bad:
  593.     comp->sls_i_error++;
  594.     comp->flags |= SLF_TOSS;
  595.  
  596.     debug(("<sl_uncompress_tcp: bad packet\n"));
  597.     return NULL;
  598. }
  599.  
  600. /* Appendix A.4  Initialisation */
  601.  
  602. void
  603. sl_compress_init(comp, rslots, tslots)
  604. struct slcompress *comp;
  605. int rslots;
  606. int tslots;
  607. {
  608.     register u_int i;
  609.     register struct cstate *tstate = NULL;
  610.  
  611.     /*
  612.      * Clean out any junk left from the last time the line was used.
  613.      */
  614.     memset(comp, 0, sizeof(*comp));
  615.     if ( rslots > 0  &&  rslots < 256 ) {
  616.     comp->rstate = calloc( rslots, sizeof(struct cstate) );
  617.     comp->rslot_limit = rslots - 1;
  618.     }
  619.  
  620.     if ( tslots > 0  &&  tslots < 256 ) {
  621.     tstate = calloc( tslots, sizeof(struct cstate) );
  622.     comp->tstate = tstate;
  623.     comp->tslot_limit = tslots - 1;
  624.     }
  625.     /*
  626.      * Link the transmit states into a circular list.
  627.      */
  628.     if (tstate > 0) {
  629.     for (i = comp->tslot_limit; i > 0; --i) {
  630.         tstate[i].cs_id = i;
  631.         tstate[i].cs_next = &tstate[i - 1];
  632.     }
  633.     tstate[0].cs_id = 0;
  634.     tstate[0].cs_next = &tstate[comp->tslot_limit];
  635.     comp->last_cs = &tstate[0];
  636.     }
  637.     /*
  638.      * Make sure we don't accidentally do CID compression
  639.      * (assumes MAX_STATES < 255).
  640.      */
  641.     comp->last_recv = NO_CID;
  642.     comp->last_xmit = NO_CID;
  643.     /*
  644.      * Set proper flags
  645.      */
  646.     comp->flags = SLF_TOSS | SLF_ALLOWED;
  647. #ifdef TRYCOUNT
  648.     if (tslots > 0)
  649.     comp->on = TRYCOUNT;
  650. #else
  651.     if (tslots > 0)
  652.     comp->flags |= SLF_ON;
  653. #endif
  654. }
  655.  
  656. void
  657. sl_compress_deinit(comp)
  658. struct slcompress *comp;
  659. {
  660.     if (comp->rstate)
  661.     free(comp->rstate);
  662.     if (comp->tstate)
  663.     free(comp->tstate);
  664. }
  665.